#include "stdafx.h"
#include "Client.h"
#include "Command.h"
#include "CommandList.h"
#include <Windows.h>
#include "NetworkGameMessages.h"

void Client::createClient(char *maxNumPlayers, Model* model){
	Client::model = model;
	client = RakNet::RakPeerInterface::GetInstance();
	myGameObject = NULL;


	maxPlayers = maxNumPlayers;
	client -> Startup(atoi(maxPlayers), &RakNet::SocketDescriptor(), 1);
}

void Client::connect(char* ip, char* port, const char* password) {
	RakNet::ConnectionAttemptResult res = client->Connect(ip, atoi(port), password, strlen(password));
	RakAssert(res == RakNet::CONNECTION_ATTEMPT_STARTED);
	connected = true;
}

void Client::receivePackets() {
	for (packet=client->Receive(); packet; client->DeallocatePacket(packet), packet=client->Receive()) {
		RakNet::BitStream bsIn(packet->data,packet->length,false);
	
		switch (packet->data[0])
		{
		case NEW_COMMAND:
			bsIn.IgnoreBytes(sizeof(RakNet::MessageID));
			retreiveCommands(bsIn);
			break;
		case ID_CONNECTION_REQUEST_ACCEPTED:
			serverAddress = packet->systemAddress;
			connected = true;
			
			//make spawn command
			type = REQUEST_SPAWN_COMMAND;
			bsOut.Reset();
			bsOut.Write(type);
			client->Send(&bsOut, HIGH_PRIORITY,RELIABLE_ORDERED,0,serverAddress,false);
			break;
		}
	}
}

void Client::syncc() {
		Command* synch;
		RakNet::BitStream sync;
		RakNet::MessageID type = NEW_COMMAND;
		sync.Reset();
		sync.Write(type);
		int i;
		sync.Write((char*) &i, sizeof(int));
		synch = new SynchCommand(myGameObject->getPosition(myGameObject->getSceneNode()), myGameObject->getSceneNode()->getOrientation(), myGameObject->getID());
		synch->save(sync);
		client->Send(&sync, HIGH_PRIORITY,RELIABLE_ORDERED,0,serverAddress,false);
}

void Client::retreiveCommands(RakNet::BitStream &bs) {
	int i;
	int type;
	bs.Read((char*) &i, sizeof(int));
	
	for (int x = 0 ; x < i ; x++) {
		bs.Read((char*) &type, sizeof(int));
		Command *tmp;
		if (type == MOVECOMMAND) {
			tmp = new MoveCommand();
			tmp->load(bs);
		} else if(type == SYNCHCOMMAND) {
			tmp = new SynchCommand();
			tmp->load(bs);
		} else if (type == VIEWCOMMAND) {
			tmp = new ViewCommand();
			tmp->load(bs);
		} else if (type == SPAWNCOMMAND) {
			tmp = new SpawnCommand();
			tmp->load(bs);
			SpawnCommand* spawn = dynamic_cast<SpawnCommand*>(tmp);
			CommandList::getInstance()->addNetwork(tmp);
			CommandList::getInstance()->execute(model);
			// If it his own player that spawns, then sets an camera
			if (spawn->isMyAvatar()) {
				int z = spawn->getPlayerId();
				myGameObject = model->getPlayerAvatarByID(spawn->getPlayerId());
				CommandList::getInstance()->getGameState()->getAvatarController()->setPlayerAvatar(model->getPlayerAvatarByID(spawn->getPlayerId()));
				model->attachCamera(model->getPlayerAvatarByID(spawn->getPlayerId()));
			}
		} else if(type == DISCONNECTCOMMAND) {
			tmp = new DisconnectCommand();
			tmp->load(bs);
		} else if (type == MOVEPLAYERCOMMAND) {
			tmp = new MovePlayerCommand();
			tmp->load(bs);
		} else if (type == SHOOTCOMMAND)
		{
			tmp = new ShootCommand();
			tmp->load(bs);
		}

		if (type != SPAWNCOMMAND) {
			CommandList::getInstance()->addNetwork(tmp);
		}
	}
}


void Client::disconnect() {
	bsOut.Reset();
	RakNet::MessageID msg = REQUEST_DISCONNECT;
	bsOut.Write(msg);
	client->Send(&bsOut, HIGH_PRIORITY,RELIABLE_ORDERED,0,serverAddress,false);
	connected = false;
	RakNet::RakPeerInterface::DestroyInstance(client);
}